<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>PF: Anchors</title>
<link rev="made" href="mailto:www@openbsd.org">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="resource-type" content="document">
<meta name="description"   content="the OpenBSD FAQ page">
<meta name="keywords"      content="openbsd,faq,pf">
<meta name="distribution"  content="global">
</head>

<!--
Copyright (c) 2003-2007 Joel Knight <enabled@myrealbox.com>

Permission to use, copy, modify, and distribute this documentation for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.

THE DOCUMENTATION IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS DOCUMENTATION INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS DOCUMENTATION
-->

<body bgcolor="#ffffff" text="#000000">
<!-- Passes validator.w3.org, please keep it this way;
please, use a max of 72 chars per line -->

<a href="../../index.html">
<img alt="[OpenBSD]" height=30 width=141 src="../../images/smalltitle.gif" border="0">
</a>
<p>
[<a href="scrub.html">Previous: Scrub (Packet Normalization)</a>]
[<a href="index.html">Contents</a>]
[<a href="queueing.html">Next: Packet Queueing and Prioritization</a>]

<p>
<h1><font color="#e00000">PF: Anchors</font></h1>

<hr>

<h3>Table of Contents</h3>
<ul>
<li><a href="#intro">Introduction</a>
<li><a href="#anchors">Anchors</a>
<li><a href="#options">Anchor Options</a>
<li><a href="#manip">Manipulating Anchors</a>
</ul>

<hr>

<a name="intro"></a>
<h2>Introduction</h2>
In addition to the main ruleset, PF can also evaluate sub rulesets.
Since sub rulesets can be manipulated on the fly by using 
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pfctl&amp;sektion=8&amp;manpath=OpenBSD+4.3"
>pfctl(8)</a>, they provide a convenient way of dynamically
altering an active ruleset. Whereas a <a href="tables.html">table</a> 
is used to hold a dynamic list of addresses, a sub ruleset is used to
hold a dynamic set of filter, <tt>nat</tt>, <tt>rdr</tt>, and
<tt>binat</tt> rules.

<p>
Sub rulesets are attached to the main ruleset by using anchors.  There
are four types of <tt>anchor</tt> rules:
<ul>
<li><tt>anchor <i>name</i></tt> - evaluates all <a href="filter.html">
filter</a> rules in the anchor <i><tt>name</tt></i>
<li><tt>binat-anchor <i>name</i></tt> - evaluates all 
<a href="nat.html#binat"><tt>binat</tt></a> rules in the
anchor <i><tt>name</tt></i>
<li><tt>nat-anchor <i>name</i></tt> - evaluates all <a href="nat.html">
<tt>nat</tt></a> rules in the anchor <i><tt>name</tt></i>
<li><tt>rdr-anchor <i>name</i></tt> - evaluates all <a href="rdr.html">
<tt>rdr</tt></a> rules in the anchor <i><tt>name</tt></i>
</ul>

Anchors can be nested which allows for sub rulesets to be
chained together.
Anchor rules will be evaluated relative to the anchor in which
they are loaded.
For example, anchor rules in the main ruleset will create anchor
attachment points with the main ruleset as their parent, and anchor
rules loaded from files with the <tt>load anchor</tt> directive will
create anchor points with that anchor as their parent.

<a name="named"></a>
<a name="anchors"></a>
<h2>Anchors</h2>
An anchor is a collection of filter and/or translation rules, tables,
and other anchors that has been assigned a name.
When PF comes across an <tt>anchor</tt> rule in the main
ruleset, it will evaluate the rules contained within the
anchor point as it evaluates rules in the main ruleset.
Processing will then continue in the main ruleset unless the packet
matches a filter rule that uses the <tt>quick</tt> option or a
translation rule within the anchor in which case the match will be
considered final and will abort the evaluation of rules in both the
anchor and the main rulesets.

<p>
For example:
<blockquote>
<tt>
ext_if = "fxp0"<br>
<br>
block on $ext_if all<br>
pass &nbsp;out on $ext_if all keep state<br>
anchor goodguys
</tt>
</blockquote>

<p>
This ruleset sets a default deny policy on <tt>fxp0</tt> for both incoming and
outgoing traffic. Traffic is then statefully passed out and an anchor
rule is created named <tt>goodguys</tt>. Anchors can be populated
with rules by three methods: 
<ul>
<li>using a <tt>load</tt> rule
<li>using 
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pfctl&amp;sektion=8&amp;manpath=OpenBSD+4.3"
>pfctl(8)</a>
<li>specifying the rules inline of the main ruleset
</ul>

<p>
The <tt>load</tt> rule causes <tt>pfctl</tt> to populate the
specified anchor by reading rules from a text file.
The <tt>load</tt> rule must be placed after the <tt>anchor</tt> rule.
Example:
<blockquote>
<tt>
anchor goodguys<br>
load anchor goodguys from "/etc/anchor-goodguys-ssh"
</tt>
</blockquote>

<p>
To add rules to an anchor using <tt>pfctl</tt>, the following type of
command can be used:
<blockquote>
<tt>
# echo "pass in proto tcp from 192.0.2.3 to any port 22" \<br>
&nbsp;&nbsp;&nbsp;| pfctl -a goodguys -f -
</tt>
</blockquote>

<p>
Rules can also be saved and loaded from a text file:
<blockquote>
<tt>
# cat &gt;&gt; /etc/anchor-goodguys-www<br>
pass in proto tcp from 192.0.2.3 to any port 80<br>
pass in proto tcp from 192.0.2.4 to any port { 80 443 }<br>
<br>
# pfctl -a goodguys -f /etc/anchor-goodguys-www<br>
</tt>
</blockquote>

<p>
To load rules directly from the main ruleset, enclose the anchor rules
in a brace-delimited block:

<blockquote>
<tt>
anchor "goodguys" { <br>
&nbsp;&nbsp;&nbsp;pass in proto tcp from 192.168.2.3 to port 22<br>
}
</tt>
</blockquote>

<p>
Inline anchors can also contain more anchors.

<blockquote>
<tt>
allow = "{ 192.0.2.3 192.0.2.4 }" <br>
<br>
anchor "goodguys" { <br>
&nbsp;&nbsp;&nbsp;anchor { <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass in proto tcp from 192.0.2.3 to port 80 <br>
&nbsp;&nbsp;&nbsp;} <br>
&nbsp;&nbsp;&nbsp;pass in proto tcp from $allow to port 22<br>
}
</tt>
</blockquote>

With inline anchors the name of the anchor becomes optional.
Note how the nested anchor in the above example does not have a name.
Also note how the macro <tt>$allow</tt> is created outside of the anchor
(in the main ruleset) and is then used within the anchor.

<p>
Filter and translation rules can be loaded into an anchor using
the same syntax and options as rules loaded into the main ruleset.
One caveat, however, is that unless you're using inline anchors any 
<a href="macros.html">macros</a> that are used must also be defined 
within the anchor itself; macros that are defined in the parent ruleset
are <i>not</i> visible from the anchor.

<p>
Since anchors can be nested, it's possible to specify that all child
anchors within a specified anchor be evaluated:

<blockquote>
<tt>
anchor "spam/*"
</tt>
</blockquote>

<p>
This syntax causes each rule within each anchor attached to the
<tt>spam</tt> anchor to be evaluated.
The child anchors will be evaluated in alphabetical order but are not
descended into recursively. 
Anchors are always evaluated relative to the anchor in which they're
defined.

<p>
Each anchor, as well as the main ruleset, exist separately from
the other rulesets. Operations done on one ruleset, such as flushing the
rules, do not affect any of the others.  In addition, removing an anchor
point from the main ruleset does not destroy the anchor or any child
anchors that are attached to that anchor. An anchor is not
destroyed until it's flushed of all rules using
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pfctl&amp;sektion=8&amp;manpath=OpenBSD+4.3"
>pfctl(8)</a> and there are no child anchors within the anchor. 

<a name="options"></a>
<h2>Anchor Options</h2>
Optionally, <tt>anchor</tt> rules can specify interface, protocol,
source and destination address, tag, etc., using the same syntax as filter
rules. When such information is given, <tt>anchor</tt> rules are only
processed if the packet matches the <tt>anchor</tt> rule's definition.
For example:
<blockquote>
<tt>
ext_if = "fxp0"<br>
<br>
block on $ext_if all<br>
pass &nbsp;out on $ext_if all keep state<br>
anchor ssh in on $ext_if proto tcp from any to any port 22<br>
</tt>
</blockquote>

<p>
The rules in the anchor <tt>ssh</tt> are only evaluated for TCP
packets destined for port 22 that come in on <tt>fxp0</tt>. Rules are then added
to the <tt>anchor</tt> like so:
<blockquote>
<tt>
# echo "pass in from 192.0.2.10 to any" | pfctl -a ssh -f -
</tt>
</blockquote>

<p>
So, even though the filter rule doesn't specify an interface, protocol,
or port, the host 192.0.2.10 will only be permitted to connect using 
SSH because of the <tt>anchor</tt> rule's definition.

<p>
The same syntax can be applied to inline anchors.

<blockquote>
<tt>
allow = "{ 192.0.2.3 192.0.2.4 }" <br>
<br>
anchor "goodguys" in proto tcp { <br>
&nbsp;&nbsp;&nbsp;anchor proto tcp to port 80 { <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass from 192.0.2.3 <br>
&nbsp;&nbsp;&nbsp;} <br>
&nbsp;&nbsp;&nbsp;anchor proto tcp to port 22 { <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass from $allow<br>
&nbsp;&nbsp;&nbsp;} <br>
}
</tt>
</blockquote>


<a name="manip"></a>
<h2>Manipulating Anchors</h2>
Manipulation of anchors is performed via <tt>pfctl</tt>. It can
be used to add and remove rules from an anchor without reloading the
main ruleset.

<p>
To list all the rules in the anchor named <tt>ssh</tt>:
<blockquote>
<tt>
# pfctl -a ssh -s rules
</tt>
</blockquote>

<p>
To flush all filter rules from the same anchor:
<blockquote>
<tt>
# pfctl -a ssh -F rules
</tt>
</blockquote>

<p>
For a full list of commands, please see
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pfctl&amp;sektion=8&amp;manpath=OpenBSD+4.3"
>pfctl(8)</a>.

<p>
[<a href="scrub.html">Previous: Scrub (Packet Normalization)</a>]
[<a href="index.html">Contents</a>]
[<a href="queueing.html">Next: Packet Queueing and Prioritization</a>]

<p>
<hr>
<a href="index.html"><img height="24" width="24" src="../../images/back.gif" border="0" alt="[back]"></a> 
<a href="mailto:www@openbsd.org">www@openbsd.org</a>
<br>
<small>$OpenBSD: anchors.html,v 1.24 2008/07/27 17:13:47 nick Exp $</small>

</body>
</html> 
